package com.jy.datapipeline.export.controller;

import cn.hutool.core.map.MapUtil;
import com.google.common.collect.ImmutableMap;
import com.jy.datapipeline.common.constants.ExcelConstants;
import com.jy.datapipeline.common.support.EasyExcelSupport;
import com.jy.datapipeline.common.support.ExcelSupport;
import com.jy.datapipeline.common.util.CronUtils;
import com.jy.datapipeline.common.util.DateUtils;
import com.jy.datapipeline.common.vo.ReturnVo;
import com.jy.datapipeline.export.common.constants.KeyConstant;
import com.jy.datapipeline.export.entity.ExpTaskExecuteLogModel;
import com.jy.datapipeline.export.entity.ExpTaskModel;
import com.jy.datapipeline.export.entity.ExpTaskTemplateModel;
import com.jy.datapipeline.export.service.ExpTaskExecuteDetailLogService;
import com.jy.datapipeline.export.service.ExpTaskExecuteLogService;
import com.jy.datapipeline.export.service.ExpTaskService;
import com.mysql.cj.util.StringUtils;
import dm.jdbc.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.Trigger.TriggerState;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping(value = "/exptask/")
public class ExpTaskController {
    @Autowired
    private ExpTaskService expTaskService;
    @Autowired
    private ExpTaskExecuteLogService expTaskExecuteLogService;
    @Autowired
    private Scheduler scheduler;
    @Autowired
    private ExpTaskExecuteDetailLogService expTaskExecuteDetailLogService;

    @Resource
    private ExcelSupport excelSupport;

    @Resource
    private EasyExcelSupport easyExcelSupport;

    @RequestMapping( value = "findByList",method = RequestMethod.GET)
    @ResponseBody
    public Object findDataStoreByList(
        @RequestParam(value = "storeId",required = false) String storeId,
        @RequestParam(value = "dataSourceId",required = false) String dataSourceId,
        @RequestParam(value = "ruleId",required = false) String ruleId,
        @RequestParam(value = "taskType",required = false) String taskType,
        @RequestParam(value = "taskName",required = false) String taskName,
        @RequestParam(value = "status",required = false) String status,
        @RequestParam(value = "iDisplayStart") Integer iDisplayStart,
        @RequestParam(value = "iDisplayLength") Integer iDisplayLength,
        @RequestParam(required = false) String latestStatus
    ){
        Map<String, Object> map=new HashMap<>();
        List<Map<String,Object>> list=this.expTaskService.findExpTaskByList(taskName,taskType,iDisplayStart,iDisplayLength,storeId,ruleId,status,dataSourceId,latestStatus);
        if(list.size()>0){
            for(int i=0;i<list.size();i++){
                String taskId= list.get(i).get("task_id")==null?"":list.get(i).get("task_id").toString();
                List<Map<String,Object>> detailList =  expTaskExecuteDetailLogService.findExpTaskExecuteDetailByList(taskId, "","","",0,1);
              if(detailList.size()>0){
                  //子任务执行以后的状态
                  Map<String, Object> object = detailList.get(0);
                  if (StringUtils.isNullOrEmpty(latestStatus)) {
                      list.get(i).put("log_detail_exp_status",object.get("exp_status"));
                  }
                  list.get(i).put("log_detail_error_msg",object.get("error_msg"));
              }
              else{
                  //子任务未执行的默认状态
                  list.get(i).put("log_detail_exp_status",0);
              }

            }
        }
        Integer count=this.expTaskService.findExpTaskByCount(taskName,taskType,storeId,ruleId,status,dataSourceId, latestStatus);

        map.put("datalist",list);
        map.put("count", count);
        return map;
    }

    @RequestMapping( value = "add",method = RequestMethod.POST)
    @ResponseBody
    public Object add(
        @RequestParam(value = "ruleId",required = true) String ruleId,
        @RequestParam(value = "dataSourceId",required = true) String dataSourceId,
        @RequestParam(value = "taskName",required = true) String taskName,
        @RequestParam(value = "storeId",required = true) String storeId,
        @RequestParam(value = "taskType",required = true) int taskType,
        @RequestParam(value = "crontab",required = true) String crontab,
        @RequestParam(value = "businessName",required = true) String businessName,
        @RequestParam Integer cityCodeId,
        @RequestParam Integer isAccurate
    ){
        Map<String, Object> result=new HashMap<>();
        try{
            ExpTaskModel etm=new ExpTaskModel();
            if(taskType==2){
                if(!crontab.equals("")) {
                    String netTime = CronUtils.nextExecution(crontab);
                    if (netTime == null) {
                        result.put("status", false);
                        result.put("msg", "crontab 格式不正确");
                        return result;
                    } else {
                        Date netDate = DateUtils.parseDate(netTime, "yyyy-MM-dd HH:mm:ss");
                        etm.setNextexec_time(netDate);
                    }
                }else {
                    result.put("status", false);
                    result.put("msg", "crontab 不能为空字符");
                    return result;
                }
            }

            String taskId= "task_" + System.currentTimeMillis();

            etm.setDataSourceId(dataSourceId);
            etm.setCrontab(crontab);
            etm.setTaskId(taskId);
            etm.setTaskType(taskType);
            etm.setRuleId(ruleId);
            etm.setTaskName(taskName);
            etm.setStoreId(storeId);
            etm.setBusinessName(businessName);
            etm.setCityCodeId(cityCodeId);
            etm.setExtendColumns(ImmutableMap.of(KeyConstant.IS_ACCURATE_KEY, isAccurate));
            ExpTaskModel etmInfo=this.expTaskService.findByTaskName(taskName);

            if(etmInfo==null){
                this.expTaskService.saveExpTask(etm);
                result.put("status",true);
                result.put("msg","success");
            }else {
                result.put("status",false);
                result.put("msg","名称重复");
            }
        }catch (Exception e){
            log.error("add exception",e);
            result.put("msg","error ["+e.getMessage()+"]");
            result.put("status",false);
        }
        return result;
    }

    @RequestMapping( value = "update",method = RequestMethod.POST)
    @ResponseBody
    public Object update(
        @RequestParam(value = "ruleId",required = true) String ruleId,
        @RequestParam(value = "dataSourceId",required = true) String dataSourceId,
        @RequestParam(value = "taskName",required = true) String taskName,
        @RequestParam(value = "storeId",required = true) String storeId,
        @RequestParam(value = "taskType",required = true) int taskType,
        @RequestParam(value = "crontab",required = true) String crontab,
        @RequestParam(value = "taskId",required = true) String taskId,
        @RequestParam(value = "businessName",required = true) String businessName,
        @RequestParam Integer cityCodeId,
        @RequestParam Integer isAccurate
    ){
        Map<String, Object> result=new HashMap<>();
        try{
            ExpTaskModel etm=new ExpTaskModel();
            if(taskType==2){
                if(!crontab.equals("")) {
                    String netTime = CronUtils.nextExecution(crontab);
                    if (netTime == null) {
                        result.put("status", false);
                        result.put("msg", "crontab 格式不正确");
                        return result;
                    } else {
                        Date netDate = DateUtils.parseDate(netTime, "yyyy-MM-dd HH:mm:ss");
                        etm.setNextexec_time(netDate);
                    }
                }else {
                    result.put("status", false);
                    result.put("msg", "crontab 不能为空字符");
                    return result;
                }
            }
            etm.setDataSourceId(dataSourceId);
            if (StringUtil.isNotEmpty(crontab)) {
                etm.setCrontab(crontab);
            }
            etm.setTaskId(taskId);
            etm.setTaskType(taskType);
            etm.setRuleId(ruleId);
            etm.setTaskName(taskName);
            etm.setStoreId(storeId);
            etm.setBusinessName(businessName);
            etm.setCityCodeId(cityCodeId);
            etm.setExtendColumns(ImmutableMap.of(KeyConstant.IS_ACCURATE_KEY, isAccurate));
            boolean isUpdate=false;
            ExpTaskModel etmInfo=this.expTaskService.findByTaskId(taskId);
            if(etmInfo!=null){
                if(!taskName.equals(etmInfo.getTaskName())){
                    ExpTaskModel etmInfo2=this.expTaskService.findByTaskName(taskName);
                    if(etmInfo2!=null){
                        result.put("status",false);
                        result.put("msg","名称重复");
                        return result;
                    }else{
                        isUpdate=this.expTaskService.updateExpTask(etm);
                    }

                }else{
                    isUpdate=this.expTaskService.updateExpTask(etm);
                }
                result.put("status",isUpdate);
                result.put("msg",isUpdate?"success":"修改失败");
            }else{
                result.put("status",false);
                result.put("msg","导出任务不存在");
            }


        }catch (Exception e){
            log.error("update exception");
            result.put("msg","error ["+e.getMessage()+"]");
            result.put("status",false);
        }
        return result;
    }

    @RequestMapping( value = "deleteByTaskId",method = RequestMethod.POST)
    @ResponseBody
    public Object deleteById(
        @RequestParam(value = "taskIds",required = true) String taskIds
    ){
        Map<String, Object> result=new HashMap<>();
        try{

            //查询是否有进行中的任务
            String[] taskidArray=taskIds.split(",");
            if(taskidArray.length>0){
                for (int i=0;i<taskidArray.length;i++){
                    String taskId=taskidArray[i];
                    ExpTaskModel task= this.expTaskService.findByTaskId(taskId);
                    if(task!=null) {
                        if (task.getStatus()==0 || task.getStatus()==2 || task.getStatus()==3) {
                            boolean flag = this.expTaskService.deleteExpTask(taskId);
                            //删除任务明细
                            this.expTaskExecuteLogService.deleteByTaskId(taskId);
                            this.expTaskExecuteDetailLogService.deleteByTaskId(taskId);
                            TriggerKey triggerKey = TriggerKey.triggerKey(taskId);
                            scheduler.pauseTrigger(triggerKey);// 停止触发器
                            scheduler.unscheduleJob(triggerKey);// 移除触发器
                            scheduler.deleteJob(JobKey.jobKey(taskId));// 删除任务
                            result.put("status", flag);
                            result.put("msg", "success");
                        } else {
                            result.put("status", false);
                            result.put("msg", "当前任务["+task.getTaskName()+"]在执行中,不能删除");
                            return result;
                        }
                    }else{
                        result.put("status", false);
                        result.put("msg", "当前任务不存在");
                        return result;
                    }
                }
            }

        }catch (Exception e){
            log.error("deleteById exception");
            result.put("msg","error ["+e.getMessage()+"]");
            result.put("status",false);
        }
        return result;
    }

    @RequestMapping( value = "findByTaskId",method = RequestMethod.GET)
    @ResponseBody
    public Object findByRuleDetailId(
        @RequestParam(value = "taskId",required = true) String taskId
    ){
        Map<String, Object> result=new HashMap<>();
        try{
            ExpTaskModel erm= this.expTaskService.findByTaskId(taskId);
            result.put("data",erm);
            result.put("status",true);
            result.put("msg","success");
        }catch (Exception e){
            log.error("findAll exception");
            result.put("msg","error ["+e.getMessage()+"]");
            result.put("status",false);
        }
        return result;
    }

    @RequestMapping( value = "rightAwayTask",method = RequestMethod.POST)
    @ResponseBody
    public Object rightAwayTask(
        @RequestParam(value = "taskId",required = true) String taskId
    ){
        Map<String, Object> result=new HashMap<>();
        boolean status=true;
        String msg="success";
        try{
          ExpTaskModel task=  this.expTaskService.findByTaskId(taskId);
          if(task!=null){
              if(task.getTaskType()==1) {
                  boolean flag=this.expTaskService.updateExpTaskStatus(1, taskId,null);
                  ExpTaskExecuteLogModel executeLogModel= this.expTaskExecuteLogService.startTaskExeucte(task);
                  if(executeLogModel!=null){
                    this.expTaskExecuteLogService.executeTask(task,executeLogModel);
                  }
                  result.put("status", flag);
                  result.put("msg", flag?"success":"执行失败");
              }else{
                  result.put("status", false);
                  result.put("msg", "当前任务是定时任务,不能立即执行");

              }

          }else{
              result.put("status", false);
              result.put("msg", "当前任务不存在");
          }


        }catch (Exception e){
            log.error("deleteById exception",e);
            result.put("msg","error ["+e.getMessage()+"]");
            result.put("status",false);
        }

        return result;
    }

    @RequestMapping( value = "startTask",method = RequestMethod.POST)
    @ResponseBody
    public Object startTask(
        @RequestParam(value = "taskId",required = true) String taskId
    ){
        Map<String, Object> result=new HashMap<>();
        boolean status=true;
        String msg="success";
        try{
            ExpTaskModel task=  this.expTaskService.findByTaskId(taskId);
            if(task!=null){
                if(task.getTaskType()==2) {
                    String netTime= CronUtils.nextExecution(task.getCrontab());
                    boolean flag=this.expTaskService.updateExpTaskStatus(1, taskId,netTime);
                    //scheduler.triggerJob(JobKey.jobKey(""));

                    TriggerKey triggerKey = TriggerKey.triggerKey(taskId);
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
                    if(triggerState.name().equals(TriggerState.PAUSED.name())) {
                        scheduler.resumeTrigger(TriggerKey.triggerKey(taskId));
                    }
                    result.put("status", flag);
                    result.put("msg", flag?"success":"执行失败");
                }else{
                    result.put("status", false);
                    result.put("msg", "当前任务是立即开始任务");

                }

            }else{
                result.put("status", false);
                result.put("msg", "当前任务不存在");
            }
        }catch (Exception e){
            log.error("deleteById exception");
            result.put("msg","error ["+e.getMessage()+"]");
            result.put("status",false);
        }

        return result;
    }



    @RequestMapping( value = "stopTask",method = RequestMethod.POST)
    @ResponseBody
    public Object stopTask(
        @RequestParam(value = "taskId",required = true) String taskId
    ){
        boolean status=true;
        String msg="success";
        Map<String, Object> result=new HashMap<>();
        try{
            ExpTaskModel task=  this.expTaskService.findByTaskId(taskId);
            if(task!=null){
                if(task.getStatus()==1) {
                    String netTime= CronUtils.nextExecution(task.getCrontab());
                    boolean flag=this.expTaskService.updateExpTaskStatus(0, taskId,netTime);
                    //job

//                    TriggerKey triggerKey = TriggerKey.triggerKey(taskId);
//                    Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
//                    if(triggerState.name().equals(TriggerState.NONE)) {
                        scheduler.pauseTrigger(TriggerKey.triggerKey(taskId));
//                    }



                    //停止任务
                    result.put("status", flag);
                    result.put("msg", flag?"success":"停止失败");
                }else{
                    result.put("status", false);
                    result.put("msg", "当前任务还未开始执行");

                }

            }else{
                result.put("status", false);
                result.put("msg", "当前任务不存在");
            }

        }catch (Exception e){
            log.error("deleteById exception");
            result.put("msg","error ["+e.getMessage()+"]");
            result.put("status",false);
        }

        return result;
    }

    @GetMapping("/download")
    public void downloadTaskTemplate(HttpServletResponse res) throws IOException {
        excelSupport.downloadTemplate(res, ExcelConstants.EXPORT_TASK_TEMPLATE_COLUMNS,
                ExcelConstants.EXPORT_TASK_TEMPLATE_COMMENTS,
                ExcelConstants.EXPORT_TASK_TEMPLATE_SHEET_NAME,
                ExcelConstants.EXPORT_TASK_TEMPLATE_EXAMPLE,
                ExcelConstants.EXPORT_TASK_TEMPLATE_NAME
        );
    }

    @PostMapping("/upload")
    public Map<String, Object> uploadTaskTemplate(@RequestBody MultipartFile file) throws IOException {
        easyExcelSupport.analysisTemplate(file.getInputStream(), 10, expTaskService, ExpTaskTemplateModel.class);
        return ReturnVo.ok();
    }
}
